package com.xingkeduo.configuration;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;


/**
 * redis队列操作
 */
@Service("redisListOpsService")
public class RedisListOpsService {
	
	private static final Logger log = LoggerFactory.getLogger(RedisListOpsService.class);
	/**
	 * redis锁默认有效时间，永久
	 */
	public static long DEFULATE_LOCK_TIME = -1;
	
    @Autowired
    public StringRedisTemplate stringRedisTemplate;
    
    /**
     * 压栈
     * 在名称为key的list头添加一个值为value的 元素
     * @param key
     * @param value
     * @return
     */
    public Long push(String key, String value) {
    	return stringRedisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 出栈
     * 返回并删除名称为key的list中的首元素
     * @param key
     * @return
     */
    public String pop(String key) {
        return stringRedisTemplate.opsForList().rightPop(key);
    }

    /**
     * 入队
     * (在名称为key的list尾添加一个值为value的元素)	
     * @param key
     * @param value
     * @return
     */
    public Long in(String key, String value) {
        return stringRedisTemplate.opsForList().leftPush(key, value);
    }
    
     /**
     * 出队
     * 回并删除名称为key的list中的首元素	
     * @param key
     * @return
     */
    public String out(String key) {
        return stringRedisTemplate.opsForList().rightPop(key);
    }

    /**
     * 栈/队列长
     *
     * @param key
     * @return
     */
    public Long length(String key) {
        return stringRedisTemplate.opsForList().size(key);
    }

    /**
     * 范围检索
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<String> range(String key, int start, int end) {
        return stringRedisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 移除
     *
     * @param key
     * @param i
     * @param value
     */
    public void remove(String key, long i, String value) {
        stringRedisTemplate.opsForList().remove(key, i, value);
    }

    /**
     * 检索
     *
     * @param key
     * @param index
     * @return
     */
    public String index(String key, long index) {
        return stringRedisTemplate.opsForList().index(key, index);
    }

    /**
     * 置值
     *
     * @param key
     * @param index
     * @param value
     */
    public void set(String key, long index, String value) {
        stringRedisTemplate.opsForList().set(key, index, value);
    }

    /**
     * 普通的K-V操作，置值
     *
     * @param key
     * @param value
     */
    public void setValue(String key, String value, long expire) {
        stringRedisTemplate.opsForValue().set(key, value, expire);
    }

    /**
     * 普通的K-V操作，取值
     *
     * @param key
     * @return
     */
    public String getValue(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * 裁剪
     *
     * @param key
     * @param start
     * @param end
     */
    public void trim(String key, long start, int end) {
        stringRedisTemplate.opsForList().trim(key, start, end);
    }
    /**
     * 获取锁；返回true:获取到锁；返回false：未获取到锁
     * @param key
     * @param value
     * @param time 有效期，单位毫秒
     * @return
     */
    public boolean locked(String key, String value, long seconds){
    	try {
    	boolean locked = stringRedisTemplate.opsForValue().setIfAbsent(key , value);
    	if(locked && seconds>0){
    		log.info("==============>>redis "+key+"  value="+value+" lock liveTime(ms):"+seconds);
    		stringRedisTemplate.expire(key, seconds, TimeUnit.MILLISECONDS);
    	}
    	return locked;
    	}catch(Exception e) {
    		log.error("锁定异常,e:{}",e);
    	}
    	return true;
//    	if(StringUtils.isNotEmpty(stringRedisTemplate.boundValueOps(key).getAndSet(value))){
//    		stringRedisTemplate.expire(key, seconds, TimeUnit.MILLISECONDS);
//    		return false;
//    	}else{
//    		return true;
//    	}
    }
    
    /**
     * 获取加锁的值
     * @param key
     * @return
     */
    public String getLockValue(String key){
    	return stringRedisTemplate.opsForValue().get(key);
    }
    
//    public boolean locked2(String key, String value, long time){
//    	final String keyf = (String) key;  
//        final Object valuef = value;  
//        final long liveTime = time / 1000;
//		return stringRedisTemplate.execute(new RedisCallback<Boolean>() {
//			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
//				byte[] rawKey = keyf.getBytes();  
//                byte[] rawValue = toByteArray(valuef);  
//                boolean locked = connection.setNX(rawKey, rawValue);
//                if (locked && liveTime > 0) {
//                	log.info("==============>>redis lock liveTime:"+liveTime);
//                    connection.expire(rawKey, liveTime);
//                }
//				return locked;
//			}
//		}, true);
//    }
    /**
     * 释放锁
     * @param key
     * @return
     */
    public void unlock(String key){
    	try {
    		stringRedisTemplate.delete(key);
    	}catch(Exception e) {
    		log.error("解除锁定异常,e:{}",e);
    	}
    }
    
    /**
     * 如果获取到锁；返回true: ；未获取到锁：返回false ，默认有效时间10秒
     * @param key
     * @param value
     * @return
     */
    public boolean locked(String key, String value){
    	return locked(key, value, DEFULATE_LOCK_TIME);
    }
    
    /**
     * 根据给定的KEY，获取自增序列，从1开始自增
     * @param key
     * @return -1：为错误，正常为1开始的正整数
     */
    public int getSequence(String key){
//    	long _time1 =  System.currentTimeMillis();
//    	try{
//	    	//获取是否锁定标记
//	    	boolean locked = locked(RedisKeyLockEnum.LOCK_SEQUENCE.getKeyName(key),_time1+"");
//	    	//true:已经锁定，则等待100ms
//	    	while (locked){
//	    		try {
//					Thread.currentThread();
//					Thread.sleep(100);
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//					return -1;
//				}
//	    		locked = locked(RedisKeyLockEnum.LOCK_SEQUENCE.getKeyName(key),_time1+"");
//	    	}
//	    	Integer val = (Integer)redisCache.get(key);
//			if(val==null){
//				redisCache.set(key, (int)2, -1);
//				return 1;
//			}else{
//				redisCache.set(key, val+1);
//				return val;
//			}
//    	}catch(Exception ex){
//    		ex.printStackTrace();
//    		return -1;
//    	}finally {
//			unlock(RedisKeyLockEnum.LOCK_SEQUENCE.getKeyName(key));
//			long _time2 = System.currentTimeMillis();
//			log.info(":::[RedisListOpsService.getSequence get Sequence time(ms) ]::::::"+ (_time2-_time1));
//		}
    	return 0;
    }
    
//    public long lockedTime(String key, String value){
//    	final String keyf = (String) key;  
//    	final Object valuef = value;  
//    	Object locked = stringRedisTemplate.execute(new RedisCallback<Boolean>(){
//    		@Override
//    		public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
//    			byte[] keyb = keyf.getBytes();  
//    			byte[] valueb = toByteArray(valuef);  
//    			Boolean locked = connection.nx
//    			return locked;
//    		}
//    	});
//    	
//    	return locked==null ? -1 : (Long) locked;
//    }
    
    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }
//    /** 
//     * 描述 : <Object转byte[]>. <br> 
//     * <p> 
//     * <使用方法说明> 
//     * </p> 
//     *  
//     * @param obj 
//     * @return 
//     */  
//    private byte[] toByteArray(Object obj) {  
//        byte[] bytes = null;  
//        ByteArrayOutputStream bos = new ByteArrayOutputStream();  
//        try {  
//            ObjectOutputStream oos = new ObjectOutputStream(bos);  
//            oos.writeObject(obj);  
//            oos.flush();  
//            bytes = bos.toByteArray();  
//            oos.close();  
//            bos.close();  
//        } catch (IOException ex) {  
//            ex.printStackTrace();  
//        }  
//        return bytes;  
//    }  

}
